/*
** listener.c -- a datagram sockets "server" demo
 *
 *
 * http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#datagram
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/timeb.h>
#include<stdint.h>

//#define MYPORT "4950"    // the port users will be connecting to

#define MAXBUFLEN 100

// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa)
{
    if (sa->sa_family == AF_INET) {
        return &(((struct sockaddr_in*)sa)->sin_addr);
    }

    return &(((struct sockaddr_in6*)sa)->sin6_addr);
}

int main(int argc, char *argv[])
{
    int sockfd,portno;
    struct addrinfo hints, *servinfo, *p;
    int rv;
    int numbytes;
    struct sockaddr_storage their_addr;
    unsigned char buf[MAXBUFLEN];
    size_t addr_len;
    char s[INET6_ADDRSTRLEN];
    
    int done = 1;
    
     //Data read from file
     uint8_t address;
     uint32_t timestamp_milli, timestamp_sec;
     uint8_t class;
     uint32_t packetnumber;
     int payload;
     uint32_t time1_sec, time_diff_sec;
     uint32_t time1_milli;
     float delay;
     float delay_s;
     float RXtimestamp;
     float Pcktimestamp;
     
       uint8_t data;
    
    struct timeb tp;
     FILE *fp;
     fp=fopen("output.txt", "w");
    
    //Write output to file
    fprintf(fp, "Address\tClass\tPacketnumber\tDelay\tPckTimeStamp\tRXTimeStamp\n");
        
     //close file
    fclose(fp);
    
    
    
    if (argc != 2) {
        fprintf(stderr,"usage: listener port\n");
        exit(1);
    }

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC; // set to AF_INET to force IPv4
    hints.ai_socktype = SOCK_DGRAM;
    hints.ai_flags = AI_PASSIVE; // use my IP
    //Added
    //hints.ai_addr =INADDR_ANY;  
    
    
    // serv_addr.sin_port = htons(portno);
    
    //portno = atoi(argv[1]);
    
    //printf("Port number:  %i",portno);
    
    
    if ((rv = getaddrinfo(NULL, argv[1], &hints, &servinfo)) != 0) {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
        return 1;
    }
   
    
    //if ((rv = getaddrinfo(NULL, portno, &hints, &servinfo)) != 0) {
    //    fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
    //    return 1;
    //}
    

    // loop through all the results and bind to the first we can
    for(p = servinfo; p != NULL; p = p->ai_next) {
        if ((sockfd = socket(p->ai_family, p->ai_socktype,
                p->ai_protocol)) == -1) {
            perror("listener: socket");
            continue;
        }

        if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
            close(sockfd);
            perror("listener: bind");
            continue;
        }

        break;
    }

    if (p == NULL) {
        fprintf(stderr, "listener: failed to bind socket\n");
        return 2;
    }else
    {
        
    }

    freeaddrinfo(servinfo);

    printf("listener: waiting to recvfrom...\n");

    addr_len = sizeof their_addr;
    
    //Open file again, this time append data
     fp=fopen("output.txt", "a");
    
    
    do
    {
        if ((numbytes = recvfrom(sockfd, buf, MAXBUFLEN-1 , 0,
            (struct sockaddr *)&their_addr, &addr_len)) == -1) {
            perror("recvfrom");
            exit(1);
        }
        
        ftime(&tp);
        
        //printf("listener: got packet from %s\n",
        //    inet_ntop(their_addr.ss_family,
        //        get_in_addr((struct sockaddr *)&their_addr),
        //            s, sizeof s));
        
       
        
        
        //printf("listener: packet is %d bytes long\n", numbytes);
      
        
            
         
         
         time1_sec = tp.time;
            
         //Destination Address   Timestamp       Class       Packet number       Payload
         //  Byte 1                      Byte 2 - 5          Byte 6      Byte 7 - 10             Byte 11 - 100
        
         //address = int(buffer[0]);
         address = (buf[0] & 255);
         printf("Address: %u \n",address);
         printf("Buf[0]: %u \n",buf[0]);
            
            
         //Timestamp
         timestamp_milli = 0;
         timestamp_milli = buf[2];
         timestamp_milli  <<= 8;
         timestamp_milli = timestamp_milli | buf[1];
            
         timestamp_sec = 0;
         timestamp_sec = buf[4];
         timestamp_sec  <<= 8;
         timestamp_sec = timestamp_sec | buf[3];
            
         timestamp_sec = (timestamp_sec & 65535);
          
         printf("time RX = %ld.%d\n",tp.time,tp.millitm);  
         printf("timestamp = %u.%u\n",timestamp_sec, timestamp_milli);
        
         // class = int(buffer[5]);
         class = buf[5];
         printf("Class: %u\n",class);
            
         //Do the calculations here.
            
         //Calculate the delay
         time_diff_sec =(time1_sec & 65535) - timestamp_sec;
         printf("time diff: %u\n",time_diff_sec);
            
            
         delay = (float) time_diff_sec + (tp.millitm/1000.0); // - (timestamp_milli/1000.0);
            
         printf("Delay: %f\n",delay );
            
         delay_s = timestamp_milli/1000.0;
            
         printf("Delay S: %f\n",delay_s );
            
         delay = delay - delay_s;
         
         Pcktimestamp = timestamp_sec + delay_s;
         RXtimestamp = (time1_sec & 65535) + (tp.millitm/1000.0);
         
         printf("Delay: %f\n",delay );
         //printf("Payload: \n");
         //for (i = 10; i <100; i++)
         //{
         //    //payload = int(buffer[i]);
         //    payload = buffer[i];
         //    printf("%i",payload);
         //}
            
            
            
         //Calculate the packet number
         packetnumber = buf[9]; 
         int cc;
         for ( cc = 1; cc < 4; cc++)
          {
              packetnumber <<= 8;
              packetnumber = packetnumber | buf[9 - cc];
          }
            
         printf("Packet number %i\n",packetnumber);

         //n = write(newsockfd,"I got your message",18);
         //if (n < 0) error("ERROR writing to socket");
            
         //Write output to file
         fprintf(fp, "%u \t %u \t %i \t %f  \t %f \t %f \n",address, class, packetnumber, delay, Pcktimestamp, RXtimestamp);
            
         
        
         data = buf[10];
         printf("Buf[10] :  %u\n\n", data);
        
    }while(data != 255);  //Loop indefinitely
    
     
     //close file
     fclose(fp);
     
    close(sockfd);

    return 0;
}